home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / Class1.c++ next >
C/C++ Source or Header  |  1994-08-01  |  20KB  |  768 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/Class1.c++,v 1.50 1994/03/20 17:27:48 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25.  
  26. /*
  27.  * EIA/TIA-578 (Class 1) Modem Driver.
  28.  */
  29. #include "Class1.h"
  30. #include "ModemConfig.h"
  31. #include "HDLCFrame.h"
  32. #include "t.30.h"
  33. #include "tiffio.h"
  34.  
  35. #include <stdlib.h>
  36. #include <ctype.h>
  37.  
  38. const char* Class1Modem::modulationNames[6] = {
  39.     "v.21, chan 2",
  40.     "v.27ter fallback mode",
  41.     "v.27ter",
  42.     "v.29",
  43.     "v.17",
  44.     "v.33",
  45. };
  46. /*
  47.  * Modem capabilities are queried at startup and a
  48.  * table based on this is created for each modem.
  49.  * This information is used to negotiate T.30 session
  50.  * parameters (e.g. signalling rate).
  51.  *
  52.  * NB: v.17 w/ long training is the same as v.33, at
  53.  *     least at 12000 and 14400.
  54.  */
  55. const Class1Cap Class1Modem::basicCaps[15] = {
  56.     {  3,  0,         0,             V21, FALSE }, // v.21
  57.     {  24, BR_2400,    DCSSIGRATE_2400V27,  V27, FALSE }, // v.27 ter
  58.     {  48, BR_4800,    DCSSIGRATE_4800V27,  V27, FALSE }, // v.27 ter
  59.     {  72, BR_7200,    DCSSIGRATE_7200V29,  V29, FALSE }, // v.29
  60.     {  73, BR_7200,    DCSSIGRATE_7200V17,  V17, FALSE }, // v.17
  61.     {  74, BR_7200,    DCSSIGRATE_7200V17,  V17, FALSE }, // v.17 w/st
  62.     {  96, BR_9600,    DCSSIGRATE_9600V29,  V29, FALSE }, // v.29
  63.     {  97, BR_9600,    DCSSIGRATE_9600V17,  V17, FALSE }, // v.17
  64.     {  98, BR_9600,    DCSSIGRATE_9600V17,  V17, FALSE }, // v.17 w/st
  65.     { 121, BR_12000,    DCSSIGRATE_12000V33, V33, FALSE }, // v.33
  66.     { 121, BR_12000,    DCSSIGRATE_12000V17, V17, FALSE }, // v.17
  67.     { 122, BR_12000,    DCSSIGRATE_12000V17, V17, FALSE }, // v.17 w/st
  68.     { 145, BR_14400,    DCSSIGRATE_14400V33, V33, FALSE }, // v.33
  69.     { 145, BR_14400,    DCSSIGRATE_14400V17, V17, FALSE }, // v.17
  70.     { 146, BR_14400,    DCSSIGRATE_14400V17, V17, FALSE }, // v.17 w/st
  71. };
  72. #define    NCAPS    (sizeof (basicCaps) / sizeof (basicCaps[0]))
  73.  
  74. Class1Modem::Class1Modem(FaxServer& s, const ModemConfig& c) : FaxModem(s,c)
  75. {
  76.     group3opts = 0;
  77.     memcpy(xmitCaps, basicCaps, sizeof (basicCaps));
  78.     memcpy(recvCaps, basicCaps, sizeof (basicCaps));
  79. }
  80.  
  81. Class1Modem::~Class1Modem()
  82. {
  83. }
  84.  
  85. /*
  86.  * Check if the modem is a Class 1 modem and,
  87.  * if so, configure it for use.
  88.  */
  89. fxBool
  90. Class1Modem::setupModem()
  91. {
  92.     if (!selectBaudRate(conf.maxRate, conf.flowControl, conf.flowControl))
  93.     return (FALSE);
  94.     // Query service support information
  95.     if (atQuery("+FCLASS=?", modemServices, 500))
  96.     traceBits(modemServices & SERVICE_ALL, serviceNames);
  97.     if ((modemServices & SERVICE_CLASS1) == 0)
  98.     return (FALSE);
  99.     atCmd(conf.class1Cmd);
  100.  
  101.     /*
  102.      * Query manufacturer, model, and firmware revision.
  103.      * We use the manufacturer especially as a key to
  104.      * working around firmware bugs (yech!).
  105.      */
  106.     if (setupManufacturer(modemMfr)) {
  107.     modemCapability("Mfr \"%s\"", (char*) modemMfr);
  108.     modemMfr.raisecase();
  109.     }
  110.     (void) setupModel(modemModel);
  111.     (void) setupRevision(modemRevision);
  112.     if (modemModel != "")
  113.     modemCapability("Model \"%s\"", (char*) modemModel);
  114.     if (modemRevision != "")
  115.     modemCapability("Revision \"%s\"", (char*) modemRevision);
  116.  
  117.     /*
  118.      * Get modem capabilities and calculate best signalling
  119.      * rate, data formatting capabilities, etc. for use in
  120.      * T.30 negotiations.
  121.      */
  122.     if (!class1Query("+FTM=?", xmitCaps)) {
  123.     serverTrace("Error parsing \"+FTM\" query response: \"%s\"", rbuf);
  124.     return (FALSE);
  125.     }
  126.     modemParams.br = 0;
  127.     u_int i;
  128.     for (i = 1; i < NCAPS; i++)
  129.     if (xmitCaps[i].ok)
  130.         modemParams.br |= BIT(xmitCaps[i].br);
  131.     modemParams.vr = VR_ALL;
  132.     modemParams.wd = BIT(WD_1728) | BIT(WD_2048) | BIT(WD_2432);
  133.     modemParams.ln = LN_ALL;
  134.     modemParams.df = BIT(DF_1DMR) | BIT(DF_2DMR);
  135.     modemParams.ec = 0;
  136.     modemParams.bf = 0;
  137.     modemParams.st = ST_ALL;
  138.     traceModemParams();
  139.     /*
  140.      * Receive capabilities are maintained separately from
  141.      * transmit capabilities because we need to know more
  142.      * than the signalling rate to formulate the DIS.
  143.      */ 
  144.     if (!class1Query("+FRM=?", recvCaps)) {
  145.     serverTrace("Error parsing \"+FRM\" query response: \"%s\"", rbuf);
  146.     return (FALSE);
  147.     }
  148.     u_int mods = 0;
  149.     for (i = 1; i < NCAPS; i++)
  150.     if (recvCaps[i].ok)
  151.         mods |= BIT(recvCaps[i].mod);
  152.     switch (mods) {
  153.     case BIT(V27FB):
  154.     discap = DISSIGRATE_V27FB;
  155.     break;
  156.     case BIT(V27):
  157.     discap = DISSIGRATE_V27;
  158.     break;
  159.     case BIT(V29):
  160.     discap = DISSIGRATE_V29;
  161.     break;
  162.     case BIT(V27)|BIT(V29):
  163.     discap = DISSIGRATE_V27|DISSIGRATE_V29;
  164.     break;
  165.     case BIT(V27)|BIT(V29)|BIT(V33):
  166.     discap = 0xE;
  167.     break;
  168.     case BIT(V27)|BIT(V29)|BIT(V33)|BIT(V17):
  169.     discap = 0xD;
  170.     break;
  171.     }
  172.     frameRev = TIFFGetBitRevTable(conf.hostFillOrder != conf.frameFillOrder);
  173.  
  174.     setupClass1Parameters();
  175.     return (TRUE);
  176. }
  177.  
  178. /*
  179.  * Send the modem the Class 1 configuration commands.
  180.  */
  181. fxBool
  182. Class1Modem::setupClass1Parameters()
  183. {
  184.     if (modemServices & SERVICE_CLASS1) {
  185.     atCmd(conf.class1Cmd);
  186.     if (conf.setupAACmd != "")
  187.         atCmd(conf.setupAACmd);
  188.     }
  189.     return (TRUE);
  190. }
  191.  
  192. /*
  193.  * Set the local subscriber identification.
  194.  */
  195. void
  196. Class1Modem::setLID(const fxStr& number)
  197. {
  198.     encodeTSI(lid, number);
  199. }
  200.  
  201. /*
  202.  * Construct a binary TSI/CIG string for transmission.  This
  203.  * is encoded as a string of hex digits according to Table 3/T.30
  204.  * (see the spec).  Hyphen ('-') and period are converted to space;
  205.  * otherwise invalid characters are ignored in the conversion.
  206.  * The string may be at most 20 characters (according to the spec).
  207.  */
  208. void
  209. Class1Modem::encodeTSI(fxStr& binary, const fxStr& ascii)
  210. {
  211.     u_char buf[20];
  212.     u_int n = fxmin(ascii.length(),(u_int) 20);
  213.     const u_char* bitrev =
  214.     TIFFGetBitRevTable(conf.hostFillOrder != FILLORDER_LSB2MSB);
  215.     for (u_int i = 0, j = 0; i < n; i++) {
  216.     for (const char* dp = "00112233445566778899  ++- . "; *dp; dp += 2)
  217.         if (dp[0] == ascii[i]) {
  218.         buf[j++] = bitrev[dp[1]];
  219.         break;
  220.         }
  221.     }
  222.     /*
  223.      * Now ``reverse copy'' the string.
  224.      */
  225.     binary.resize(20);
  226.     for (i = 0; j > 0; i++, j--)
  227.     binary[i] = buf[j-1];
  228.     for (; i < 20; i++)
  229.     binary[i] = bitrev[' '];    // blank pad remainder
  230. }
  231.  
  232. /*
  233.  * Do the inverse of encodeTSI; i.e. convert a binary
  234.  * string of encoded digits into the equivalent ascii.
  235.  */
  236. void
  237. Class1Modem::decodeTSI(fxStr& ascii, const HDLCFrame& binary)
  238. {
  239.     int n = binary.getFrameDataLength();
  240.     if (n > 20)            // spec says no more than 20 digits
  241.     n = 20;
  242.     ascii.resize(n);
  243.     const u_char* bitrev =
  244.     TIFFGetBitRevTable(conf.hostFillOrder != FILLORDER_LSB2MSB);
  245.     u_int d = 0;
  246.     fxBool seenDigit = FALSE;
  247.     for (const u_char* cp = binary.getFrameData() + n-1; n > 0; cp--, n--) {
  248.     /*
  249.      * Accept any printable ascii.
  250.      */
  251.     u_char c = bitrev[*cp];
  252.         if (isprint(c) || c == ' ') {
  253.         if (c != ' ')
  254.         seenDigit = TRUE;
  255.         if (seenDigit)
  256.         ascii[d++] = c;
  257.     }
  258.     }
  259.     ascii.resize(d);
  260. }
  261.  
  262. /*
  263.  * Pass data to modem, filtering DLE's and
  264.  * optionally including the end-of-data
  265.  * marker <DLE><ETX>.
  266.  */
  267. fxBool
  268. Class1Modem::sendClass1Data(const u_char* data, u_int cc,
  269.     const u_char* bitrev, fxBool eod)
  270. {
  271.     if (!putModemDLEData(data, cc, bitrev, getDataTimeout()))
  272.     return (FALSE);
  273.     if (eod) {
  274.     u_char buf[2];
  275.     buf[0] = DLE;
  276.     buf[1] = ETX;
  277.     return (putModemData(buf, 2));
  278.     } else
  279.     return (TRUE);
  280. }
  281.  
  282. /*
  283.  * Receive timed out, abort the operation
  284.  * and resynchronize before returning.
  285.  */
  286. void
  287. Class1Modem::abortReceive()
  288. {
  289.     fxBool b = wasTimeout();
  290.     char c = CAN;            // anything other than DC1/DC3
  291.     putModem(&c, 1, 1);
  292.     /*
  293.      * If the modem handles abort properly, then just
  294.      * wait for an OK result.  Otherwise, wait a short
  295.      * period of time, flush any input, and then send
  296.      * "AT" and wait for the return "OK".
  297.      */
  298.     if (conf.class1RecvAbortOK == 0) {    // modem doesn't send OK response
  299.     pause(200);
  300.     flushModemInput();
  301.     (void) atCmd("", AT_OK, 100);
  302.     } else
  303.     (void) waitFor(AT_OK, conf.class1RecvAbortOK);
  304.     setTimeout(b);            // XXX putModem clobbers timeout state
  305. }
  306.  
  307. /*
  308.  * Receive an HDLC frame.  The timeout is against
  309.  * the receipt of the HDLC flags; the frame itself must
  310.  * be received within 3 seconds (per the spec).
  311.  * If a carrier is received, but the complete frame
  312.  * is not received before the timeout, the receive
  313.  * is aborted.
  314.  */
  315. fxBool
  316. Class1Modem::recvRawFrame(HDLCFrame& frame)
  317. {
  318.     int c;
  319.     /*
  320.      * Search for HDLC frame flags.  The
  321.      * timeout is to reception of the flags.
  322.      */
  323.     do {
  324.     c = getModemChar(0);
  325.     } while (c != EOF && c != 0xff);
  326.     stopTimeout("waiting for HDLC flags");
  327.     if (c == 0xff) {            // flags received
  328.     /*
  329.      * The spec says that a frame that takes between
  330.      * 2.55 and 3.45 seconds to be received may be
  331.      * discarded; we use 3.1 seconds as a compromise.
  332.      */
  333.     startTimeout(3100);
  334.     do {
  335.         if (c == DLE) {
  336.         c = getModemChar(0);
  337.         if (c == ETX || c == EOF)
  338.             break;
  339.         }
  340.         frame.put(frameRev[c]);
  341.     } while ((c = getModemChar(0)) != EOF);
  342.     stopTimeout("receiving HDLC frame data");
  343.     }
  344.     if (wasTimeout()) {
  345.     abortReceive();
  346.     return (FALSE);
  347.     }
  348.     traceHDLCFrame("-->", frame);
  349.     /*
  350.      * Now collect the "OK", "ERROR", or "FCERROR"
  351.      * response telling whether or not the FCS was
  352.      * legitimate.
  353.      */
  354.     if (!waitFor(AT_OK)) {
  355.     if (lastResponse == AT_FCERROR)
  356.         protoTrace("FCS error");
  357.     return (FALSE);
  358.     }
  359.     if (frame.getFrameDataLength() < 1) {
  360.     protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  361.     return (FALSE);
  362.     }
  363.     if ((frame[1]&0xf7) != 0xc0) {
  364.     protoTrace("HDLC frame with bad control field %#x", frame[1]);
  365.     return (FALSE);
  366.     }
  367.     frame.setOK(TRUE);
  368.     return (TRUE);
  369. }
  370.  
  371. #include "StackBuffer.h"
  372.  
  373. /*
  374.  * Log an HLDC frame along with a time stamp (secs.10ms).
  375.  */
  376. void
  377. Class1Modem::traceHDLCFrame(const char* direction, const HDLCFrame& frame)
  378. {
  379.     if (!getHDLCTracing())
  380.     return;
  381.     const char* hexdigits = "0123456789ABCDEF";
  382.     fxStackBuffer buf;
  383.     for (u_int i = 0; i < frame.getLength(); i++) {
  384.     u_char b = frame[i];
  385.     if (i > 0)
  386.         buf.put(' ');
  387.     buf.put(hexdigits[b>>4]);
  388.     buf.put(hexdigits[b&0xf]);
  389.     }
  390.     protoTrace("%s HDLC<%u:%.*s>", direction,
  391.     frame.getLength(), buf.getLength(), (char*) buf);
  392. }
  393.  
  394. /*
  395.  * Send a raw HDLC frame and wait for the modem response.
  396.  * The modem is expected to be an HDLC frame sending mode
  397.  * (i.e. +FTH=3 or similar has already be sent to the modem).
  398.  * The T.30 max frame length is enforced with a 3 second
  399.  * timeout on the send.
  400.  */
  401. fxBool
  402. Class1Modem::sendRawFrame(HDLCFrame& frame)
  403. {
  404.     traceHDLCFrame("<--", frame);
  405.     if (frame.getLength() < 3) {
  406.     protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
  407.     return (FALSE);
  408.     }
  409.     if (frame[0] != 0xff) {
  410.     protoTrace("HDLC frame with bad address field %#x", frame[0]);
  411.     return (FALSE);
  412.     }
  413.     if ((frame[1]&0xf7) != 0xc0) {
  414.     protoTrace("HDLC frame with bad control field %#x", frame[1]);
  415.     return (FALSE);
  416.     }
  417.     static u_char buf[2] = { DLE, ETX };
  418.     return (putModemDLEData(frame, frame.getLength(), frameRev, 0) &&
  419.     putModem(buf, 2, 0) &&
  420.     waitFor(frame.moreFrames() ? AT_CONNECT : AT_OK, 0));
  421. }
  422.  
  423. /*
  424.  * Send a single byte frame.
  425.  */
  426. fxBool
  427. Class1Modem::sendFrame(u_char fcf, fxBool lastFrame)
  428. {
  429.     HDLCFrame frame(conf.class1FrameOverhead);
  430.     frame.put(0xff);
  431.     frame.put(lastFrame ? 0xc8 : 0xc0);
  432.     frame.put(fcf);
  433.     return (sendRawFrame(frame));
  434. }
  435.  
  436. /*
  437.  * Send a frame with DCS/DIS.
  438.  */
  439. fxBool
  440. Class1Modem::sendFrame(u_char fcf, u_int dcs, fxBool lastFrame)
  441. {
  442.     HDLCFrame frame(conf.class1FrameOverhead);
  443.     frame.put(0xff);
  444.     frame.put(lastFrame ? 0xc8 : 0xc0);
  445.     frame.put(fcf);
  446.     frame.put(dcs>>24);
  447.     frame.put(dcs>>16);
  448.     frame.put(dcs>>8);
  449.     if (dcs&(DCS_XTNDFIELD<<8))
  450.     frame.put(dcs);
  451.     return (sendRawFrame(frame));
  452. }
  453.  
  454. /*
  455.  * Send a frame with TSI/CSI.
  456.  */
  457. fxBool
  458. Class1Modem::sendFrame(u_char fcf, const fxStr& tsi, fxBool lastFrame)
  459. {
  460.     HDLCFrame frame(conf.class1FrameOverhead);
  461.     frame.put(0xff);
  462.     frame.put(lastFrame ? 0xc8 : 0xc0);
  463.     frame.put(fcf);
  464.     frame.put((u_char*)(char*)tsi, tsi.length());
  465.     return (sendRawFrame(frame));
  466. }
  467.  
  468. fxBool
  469. Class1Modem::transmitFrame(u_char fcf, fxBool lastFrame)
  470. {
  471.     startTimeout(2550);            // 3.0 - 15% = 2.55 secs
  472.     fxBool frameSent =
  473.     class1Cmd("TH", 3, AT_NOTHING) &&
  474.     atResponse(rbuf, 0) == AT_CONNECT &&
  475.     sendFrame(fcf, lastFrame);
  476.     stopTimeout("sending HDLC frame");
  477.     return (frameSent);
  478. }
  479.  
  480. fxBool
  481. Class1Modem::transmitFrame(u_char fcf, u_int dcs, fxBool lastFrame)
  482. {
  483.     /*
  484.      * The T.30 spec says no frame can take more than 3 seconds
  485.      * (+/- 15%) to transmit.  We take the conservative approach.
  486.      * and guard against the send exceeding the lower bound.
  487.      */
  488.     startTimeout(2550);            // 3.0 - 15% = 2.55 secs
  489.     fxBool frameSent =
  490.     class1Cmd("TH", 3, AT_NOTHING) &&
  491.     atResponse(rbuf, 0) == AT_CONNECT &&
  492.     sendFrame(fcf, dcs, lastFrame);
  493.     stopTimeout("sending HDLC frame");
  494.     return (frameSent);
  495. }
  496.  
  497. fxBool
  498. Class1Modem::transmitFrame(u_char fcf, const fxStr& tsi, fxBool lastFrame)
  499. {
  500.     startTimeout(3000);            // give more time than others
  501.     fxBool frameSent =
  502.     class1Cmd("TH", 3, AT_NOTHING) &&
  503.     atResponse(rbuf, 0) == AT_CONNECT &&
  504.     sendFrame(fcf, tsi, lastFrame);
  505.     stopTimeout("sending HDLC frame");
  506.     return (frameSent);
  507. }
  508.  
  509. /*
  510.  * Send data using the specified signalling rate.
  511.  */
  512. fxBool
  513. Class1Modem::transmitData(int br, u_char* data, u_int cc,
  514.     const u_char* bitrev, fxBool eod)
  515. {
  516.     if (flowControl == FLOW_XONXOFF)
  517.     setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
  518.     fxBool ok = (class1Cmd("TM", br, AT_CONNECT) &&
  519.     sendClass1Data(data, cc, bitrev, eod) &&
  520.     (eod ? waitFor(AT_OK) : TRUE));
  521.     if (flowControl == FLOW_XONXOFF)
  522.     setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
  523.     return (ok);
  524. }
  525.  
  526. /*
  527.  * Receive an HDLC frame.  The timeout is against
  528.  * the receipt of the HDLC flags; the frame itself must
  529.  * be received within 3 seconds (per the spec).
  530.  * If a carrier is received, but the complete frame
  531.  * is not received before the timeout, the receive
  532.  * is aborted.
  533.  */
  534. fxBool
  535. Class1Modem::recvFrame(HDLCFrame& frame, long ms)
  536. {
  537.     frame.reset();
  538.     startTimeout(ms);
  539.     fxBool readPending = class1Cmd("RH", 3, AT_NOTHING);
  540.     if (readPending && waitFor(AT_CONNECT,0))
  541.     return recvRawFrame(frame);        // NB: stops inherited timeout
  542.     stopTimeout("waiting for v.21 carrier");
  543.     if (readPending && wasTimeout())
  544.     abortReceive();
  545.     return (FALSE);
  546. }
  547.  
  548. /*
  549.  * Receive TCF data using the specified signalling rate.
  550.  */
  551. fxBool
  552. Class1Modem::recvTCF(int br, HDLCFrame& buf, const u_char* bitrev, long ms)
  553. {
  554.     buf.reset();
  555.     if (flowControl == FLOW_XONXOFF)
  556.     setXONXOFF(FLOW_NONE, FLOW_XONXOFF, ACT_DRAIN);
  557.     startTimeout(ms);
  558.     /*
  559.      * Loop waiting for carrier or timeout.
  560.      */
  561.     fxBool readPending, gotCarrier;
  562.     do {
  563.     readPending = class1Cmd("RM", br, AT_NOTHING);
  564.     gotCarrier = readPending && waitFor(AT_CONNECT, 0);
  565.     } while (readPending && !gotCarrier && lastResponse == AT_FCERROR);
  566.     /*
  567.      * If carrier was recognized, collect the data.
  568.      */
  569.     fxBool gotData = FALSE;
  570.     if (gotCarrier) {
  571.     int c = getModemChar(0);        // NB: timeout is to first byte
  572.     stopTimeout("receiving TCF");
  573.     if (c != EOF) {
  574.         buf.reset();
  575.         /*
  576.          * Use a 2 second timer to receive the 1.5
  577.          * second TCF--perhaps this is too long to
  578.          * permit us to send the nak in time?
  579.          */
  580.         startTimeout(2000);
  581.         do {
  582.         if (c == DLE) {
  583.             c = getModemChar(0);
  584.             if (c == ETX) {
  585.             gotData = TRUE;
  586.             break;
  587.             }
  588.         }
  589.         buf.put(bitrev[c]);
  590.         } while ((c = getModemChar(0)) != EOF);
  591.     }
  592.     }
  593.     stopTimeout("receiving TCF");
  594.     /*
  595.      * If the +FRM is still pending, abort it.
  596.      */
  597.     if (readPending && wasTimeout())
  598.     abortReceive();
  599.     if (flowControl == FLOW_XONXOFF)
  600.     setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
  601.     return (gotData);
  602. }
  603.  
  604. /* 
  605.  * Modem manipulation support.
  606.  */
  607.  
  608. /*
  609.  * Reset a Class 1 modem.
  610.  */
  611. fxBool
  612. Class1Modem::reset(long ms)
  613. {
  614.     return (FaxModem::reset(ms) && setupClass1Parameters());
  615. }
  616.  
  617. ATResponse
  618. Class1Modem::atResponse(char* buf, long ms)
  619. {
  620.     if (FaxModem::atResponse(buf, ms) == AT_OTHER && strneq(buf, "+FCERROR", 8))
  621.     lastResponse = AT_FCERROR;
  622.     return (lastResponse);
  623. }
  624.  
  625. /*
  626.  * Wait (carefully) for some response from the modem.
  627.  */
  628. fxBool
  629. Class1Modem::waitFor(ATResponse wanted, long ms)
  630. {
  631.     for (;;) {
  632.     ATResponse response = atResponse(rbuf, ms);
  633.     if (response == wanted)
  634.         return (TRUE);
  635.     switch (response) {
  636.     case AT_TIMEOUT:
  637.     case AT_EMPTYLINE:
  638.     case AT_ERROR:
  639.     case AT_NOCARRIER:
  640.     case AT_NODIALTONE:
  641.     case AT_NOANSWER:
  642.     case AT_OFFHOOK:
  643.         modemTrace("ERROR: %s", ATresponses[response]);
  644.         /* fall thru... */
  645.     case AT_FCERROR:
  646.         return (FALSE);
  647.     }
  648.     }
  649. }
  650.  
  651. /*
  652.  * Interfaces for sending a Class 1 command; i.e, AT+F<cmd>
  653.  */
  654.  
  655. /*
  656.  * Send <cmd> and wait for expect
  657.  */
  658. fxBool
  659. Class1Modem::class1Cmd(const char* cmd, ATResponse expect)
  660. {
  661.      return vatFaxCmd(expect, "%s", cmd);
  662. }
  663.  
  664. /*
  665.  * Send <cmd>=<a0> and wait for expect
  666.  */
  667. fxBool
  668. Class1Modem::class1Cmd(const char* cmd, int a0, ATResponse expect)
  669. {
  670.     return vatFaxCmd(expect, "%s=%u", cmd, a0);
  671. }
  672.  
  673. /*
  674.  * Send <what>=? and get a range response.
  675.  */
  676. fxBool
  677. Class1Modem::class1Query(const char* what, Class1Cap caps[])
  678. {
  679.     char response[1024];
  680.     if (atCmd(what, AT_NOTHING) && atResponse(response) == AT_OTHER) {
  681.     sync(5000);
  682.     return (parseQuery(response, caps));
  683.     }
  684.     return (FALSE);
  685. }
  686.  
  687. /*
  688.  * Map the DCS signalling rate to the appropriate
  689.  * Class 1 capability entry.
  690.  */
  691. const Class1Cap*
  692. Class1Modem::findSRCapability(u_short sr, const Class1Cap caps[])
  693. {
  694.     for (u_int i = NCAPS-1; i > 0; i--) {
  695.     const Class1Cap* cap = &caps[i];
  696.     if (cap->sr == sr) {
  697.         if (cap->mod == V17 && HasShortTraining(cap-1))
  698.         cap--;
  699.         return (cap);
  700.     }
  701.     }
  702.     // XXX should not happen...
  703.     protoTrace("MODEM: unknown signalling rate %#x, using 9600 v.29", sr);
  704.     return findSRCapability(DCSSIGRATE_9600V29, caps);
  705. }
  706.  
  707. /*
  708.  * Map the Class 2 bit rate to the best
  709.  * signalling rate capability of the modem.
  710.  */
  711. const Class1Cap*
  712. Class1Modem::findBRCapability(u_short br, const Class1Cap caps[])
  713. {
  714.     for (u_int i = NCAPS-1; i > 0; i--) {
  715.     const Class1Cap* cap = &caps[i];
  716.     if (cap->br == br && cap->ok) {
  717.         if (cap->mod == V17 && HasShortTraining(cap-1))
  718.         cap--;
  719.         return (cap);
  720.     }
  721.     }
  722.     protoTrace("MODEM: unsupported baud rate %#x", br);
  723.     return NULL;
  724. }
  725.  
  726. /*
  727.  * Override the DIS signalling rate capabilities because
  728.  * they are defined from the Class 2 parameter information
  729.  * and do not include the modulation technique.
  730.  */
  731. u_int
  732. Class1Modem::modemDIS() const
  733. {
  734.     // NB: DIS is in 32-bit format
  735.     return (FaxModem::modemDIS() &~ (DIS_SIGRATE<<8)) | (discap<<18);
  736. }
  737.  
  738. const char COMMA = ',';
  739. const char SPACE = ' ';
  740.  
  741. /*
  742.  * Parse a Class 1 parameter string.
  743.  */
  744. fxBool
  745. Class1Modem::parseQuery(const char* cp, Class1Cap caps[])
  746. {
  747.     while (cp[0]) {
  748.     if (cp[0] == SPACE) {        // ignore white space
  749.         cp++;
  750.         continue;
  751.     }
  752.     if (!isdigit(cp[0]))
  753.         return (FALSE);
  754.     int v = 0;
  755.     do {
  756.         v = v*10 + (cp[0] - '0');
  757.     } while (isdigit((++cp)[0]));
  758.     for (u_int i = 0; i < NCAPS; i++)
  759.         if (caps[i].value == v) {
  760.         caps[i].ok = TRUE;
  761.         break;
  762.         }
  763.     if (cp[0] == COMMA)        // <item>,<item>...
  764.         cp++;
  765.     }
  766.     return (TRUE);
  767. }
  768.